//#########################################################
//#
//# Titre : 	Utilitaires CHAT LINUX Automne 13
//#			SIF-1015 - Systeme d'exploitation
//#			Universite du Quebec a� Trois-Rivieres
//#
//# Auteur : 	Francois Meunier
//#	Date :	Septembre 2013
//#
//# Langage : 	ANSI C on LINUX 
//#
//#######################################

#include "gestionListeChaineeCHAT.h"

//Pointeur vers l'écran
extern WINDOW* contentscr;

//Pointeur de tete de liste
extern struct noeud* head;

//pointeur sur la liste de threads
extern struct threadNode* headThread;
extern struct threadNode* tailThread;
extern int idMembre;

//#######################################
//#
//# Interpretation de la transaction et 
//# creation du thread approprié 
//#
void executeTransCHAT(struct Info_FIFO_Transaction infoTrx)
{	
	char *tok, *sp;
	int isInvalid = FALSE;
	char originalTransaction[TRANSACTION_SIZE];
	strcpy(originalTransaction, infoTrx.transaction);

	//Extraction du type de transaction
	tok = strtok_r(infoTrx.transaction, " ", &sp);

	if(tok != NULL && strlen(tok) == 1 )//Valide qu'il n'y a qu'un seul caratere suivi d'un espace au debut de la transaction
	{
		//Branchement selon le type de transaction
		switch(toupper(tok[0]))
		{
			case 'A':{
				//Extraction des parametres
				char *ptrNick = strtok_r(NULL, " ", &sp);
				char *ptrGroupe = strtok_r(NULL, "\n", &sp);
			
				if(ptrNick != NULL && ptrGroupe != NULL)
				{
					int lenghtNick = strlen(ptrNick);
					int lenghtGroupe = strlen(ptrGroupe);
					if(lenghtNick > 0 && lenghtNick <= MAX_CHAT_STR_LEN
					&& lenghtGroupe> 0 && lenghtGroupe <= MAX_CHAT_STR_LEN)
					{
						//Creation du parametre
						struct infoMembre* membre = (struct infoMembre*)Malloc(sizeof(struct infoMembre));
			
						//Incrementation de l'identifiant
						idMembre++;
			
						//Assignation des valeurs du parametre
						membre->identifiant = idMembre;
						strcpy(membre->ptrNick, ptrNick);
						strcpy(membre->ptrGroupe, ptrGroupe);
						membre->pid =  infoTrx.pid_client;

						//Cree le nouveau noeud dans la liste de threads
						initThreadNode(&headThread, &tailThread);
			
						Pthread_create(&(tailThread->thread), NULL, &addItemCHAT, membre);
					}
					else
					{
						isInvalid = TRUE;
					}
				}
				else
				{
					isInvalid = TRUE;
				}
				break;
				}
			case 'M':{
				//Extraction des parametres
				char* idStr = strtok_r(NULL, " ", &sp);
				int identifiant = 0;

				if(idStr != NULL)
					identifiant = atoi(idStr);
				else
					isInvalid = TRUE;

				if(isInvalid == FALSE )	
				{
					char *ptrNick = strtok_r(NULL, " ", &sp);
					char *ptrGroupe = strtok_r(NULL, "\n", &sp);
			
					if(ptrNick != NULL && ptrGroupe != NULL)
					{
						int lenghtNick = strlen(ptrNick);
						int lenghtGroupe = strlen(ptrGroupe);
						if(lenghtNick > 0 && lenghtNick <= MAX_CHAT_STR_LEN
						&& lenghtGroupe > 0 && lenghtGroupe <= MAX_CHAT_STR_LEN
						&& identifiant != 0)//Identifiant == 0 si on fait atoi() sur une chaine qui n'est pas une chiffre 							    ou ne debute pas par un chiffre et les id utilisateurs commencent a 1
						{
							//Creation du parametre
							struct infoMembre* membre = (struct infoMembre*)Malloc(sizeof(struct infoMembre));			
							//Assignation des valeurs du parametre
							membre->identifiant = identifiant;
							strcpy(membre->ptrNick, ptrNick);
							strcpy(membre->ptrGroupe, ptrGroupe);

							//Pid du client demandant							
							membre->pid =  infoTrx.pid_client;

							//Cree le nouveau noeud dans la liste de threads
							initThreadNode(&headThread, &tailThread);

							Pthread_create(&(tailThread->thread),NULL,&modifyItemCHAT,membre);
						}
						else
						{
							isInvalid = TRUE;
						}
					}
					else
					{
						isInvalid = TRUE;
					}
				}
				break;
				}
			case 'E':{
				//Extraction du parametre
				char *ptrNick = strtok_r(NULL, " ", &sp);
				char *ptrGroupe = strtok_r(NULL, "\n", &sp);

				if(ptrNick != NULL && ptrGroupe != NULL)
				{
					int lenghtNick = strlen(ptrNick);
					int lenghtGroupe = strlen(ptrGroupe);
					if(lenghtNick > 0 && lenghtNick <= MAX_CHAT_STR_LEN
					&& lenghtGroupe > 0 && lenghtGroupe <= MAX_CHAT_STR_LEN)
					{
						//Creation du parametre
						struct suppressionMembre* membre  = (struct suppressionMembre*)Malloc(sizeof(struct suppressionMembre));
		
						//Assignation des valeurs du parametre
						strcpy(membre->ptrNick, ptrNick);
						strcpy(membre->ptrGroupe, ptrGroupe);

						//Pid du client demandant
						membre->pid =  infoTrx.pid_client;
			
						//Cree le nouveau noeud dans la liste de threads
						initThreadNode(&headThread, &tailThread);
			
						Pthread_create(&(tailThread->thread), NULL, &removeItemCHAT, membre);
					}
					else
					{
						isInvalid = TRUE;
					}
				}
				else
				{
					isInvalid = TRUE;
				}
				break;
				}
			case 'L':{
				//Extraction des parametres
				char* strStart = strtok_r(NULL, "-", &sp);
				char* strEnd = strtok_r(NULL, " ", &sp);
				
				if(strStart != NULL && strEnd != NULL)
				{
					int nstart = atoi(strStart);
					int nend = atoi(strEnd);
					if(nstart != 0 && nend != 0 && nstart <= nend)
					{
						//Creation du parametre
						struct paramsIntervalle* intervalle = (struct paramsIntervalle*)Malloc(sizeof(struct paramsIntervalle));
						intervalle->debut = nstart;
						intervalle->fin = nend;
						intervalle->pid =  infoTrx.pid_client;
			
						//Cree le nouveau noeud dans la liste de threads
						initThreadNode(&headThread, &tailThread);
			
						Pthread_create(&(tailThread->thread), NULL, &listItemsCHAT, intervalle);
					}
					else
					{
						isInvalid = TRUE;
					}
				}
				else
				{
					isInvalid = TRUE;
				}
				break;
				}
			case 'T':{
				//Extraction des parametres
				char *ptrNick = strtok_r(NULL, " ", &sp);
				char *ptrGroupe = strtok_r(NULL, " ", &sp);
				char *ptrTexte = strtok_r(NULL, "\n", &sp);

				if(ptrNick != NULL && ptrGroupe != NULL  && ptrTexte != NULL)
				{
					int lenghtNick = strlen(ptrNick);
					int lenghtGroupe = strlen(ptrGroupe);
					int lenghtTexte = strlen(ptrTexte);
					if(lenghtNick > 0 && lenghtNick <= MAX_CHAT_STR_LEN
					&& lenghtGroupe > 0 && lenghtGroupe <= MAX_CHAT_STR_LEN
					&& lenghtTexte > 0 && lenghtTexte <= MAX_CHAT_STR_LEN)
					{
						//Creation du parametre
						struct paramsTexte* message = (struct paramsTexte*)Malloc(sizeof(struct paramsTexte));
						strcpy(message->ptrNick, ptrNick);
						strcpy(message->ptrGroupe, ptrGroupe);
						strcpy(message->ptrTexte, ptrTexte);
						message->pid =  infoTrx.pid_client;
			
						//Cree le nouveau noeud dans la liste de threads
						initThreadNode(&headThread, &tailThread);
			
						Pthread_create(&(tailThread->thread), NULL, &transTextCHAT, message);
					}
					else
					{
						isInvalid = TRUE;
					}
				}
				else
				{
					isInvalid = TRUE;
				}
				break;
				}
			case 'Q':{
				//Extraction des parametres
				char* strPid = strtok_r(NULL, ".", &sp);

				if(strPid != NULL)
				{
					unsigned int pid = atoi(strPid);

					if(pid > 0)
					{
						//Creation du parametre
						struct paramQuit* quitPid = (struct paramQuit*)Malloc(sizeof(struct paramQuit));
						quitPid->pid =  infoTrx.pid_client;
			
						//Cree le nouveau noeud dans la liste de threads
						initThreadNode(&headThread, &tailThread);
			
						Pthread_create(&(tailThread->thread), NULL, &quitUser, quitPid);
					}
					else
					{
						isInvalid = TRUE;
					}
				}
				else
				{
					isInvalid = TRUE;
				}
				break;
				}
			default: isInvalid = TRUE;
				break;
		}
	}
	else
	{
		isInvalid = TRUE;
	}

	if(isInvalid == TRUE)
	{
		char message[MESSAGE_SIZE];
		sprintf(message, "Transaction invalide : %s\n", originalTransaction);

		wattron(contentscr, COLOR_PAIR(RED_ON_BLACK));
		waddstr(contentscr, message);
		wrefresh(contentscr);
		wattron(contentscr, COLOR_PAIR(GREEN_ON_BLACK));

		//initialisation de la fifo client
		char nomFifoClient[FIFO_NAME_SIZE];
		memset(nomFifoClient, '\0', sizeof(nomFifoClient));
		sprintf(nomFifoClient, CLIENT_FIFO_NAME, infoTrx.pid_client);

		
		memset(message, '\0', sizeof(message));
		sprintf(message, "\nTransaction invalide!\n");
		sendMessage(nomFifoClient, 'F', message);
	}
}

//#######################################
//#
//# Initialisation d'un noeud de la liste de threads
//#
void initThreadNode(struct threadNode** head, struct threadNode** tail)
{

	struct threadNode* newThreadNode = (struct threadNode*)Malloc(sizeof(struct threadNode));	
	newThreadNode->suivant = NULL;

	if(*head == NULL)
	{
		*head = newThreadNode;
		*tail = *head;
	}
	else 
	{
		(*tail)->suivant = newThreadNode;
		*tail = (*tail)->suivant;
	}
}
